/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut
)]
use crate::common::*;
extern "C" {
    fn fclose(__stream: *mut FILE) -> libc::c_int;
    fn fopen(_: *const libc::c_char, _: *const libc::c_char) -> *mut FILE;
    fn fgets(__s: *mut libc::c_char, __n: libc::c_int, __stream: *mut FILE) -> *mut libc::c_char;
    fn rewind(__stream: *mut FILE);
    fn fileno(__stream: *mut FILE) -> libc::c_int;
    fn reallocarray(__ptr: *mut libc::c_void, __nmemb: size_t, __size: size_t)
        -> *mut libc::c_void;
    fn free(_: *mut libc::c_void);
    fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void;
    fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
    fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char;
    fn strtok_r(
        __s: *mut libc::c_char,
        __delim: *const libc::c_char,
        __save_ptr: *mut *mut libc::c_char,
    ) -> *mut libc::c_char;
    fn strlen(_: *const libc::c_char) -> libc::c_ulong;
    fn fcntl(__fd: libc::c_int, __cmd: libc::c_int, _: ...) -> libc::c_int;
    fn sysconf(__name: libc::c_int) -> libc::c_long;
    fn sudo_strtoid_v2(str: *const libc::c_char, errstr: *mut *const libc::c_char) -> id_t;
}
static mut pwf: *mut FILE = 0 as *const FILE as *mut FILE;
static mut pwfile: *const libc::c_char = b"/etc/passwd\0" as *const u8 as *const libc::c_char;
static mut pw_stayopen: libc::c_int = 0;
static mut grf: *mut FILE = 0 as *const FILE as *mut FILE;
static mut grfile: *const libc::c_char = b"/etc/group\0" as *const u8 as *const libc::c_char;
static mut gr_stayopen: libc::c_int = 0;
#[no_mangle]
pub fn setpwfile(mut file: *const libc::c_char) {
    unsafe { pwfile = file };
    if !unsafe { pwf.is_null() } {
        endpwent();
    }
}
#[no_mangle]
pub fn setpwent() {
    if unsafe { pwf.is_null() } {
        unsafe { pwf = fopen(pwfile, b"r\0" as *const u8 as *const libc::c_char) };
        if !unsafe { pwf.is_null() } {
            unsafe { fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC) };
        }
    } else {
        unsafe { rewind(pwf) };
    }
    unsafe { pw_stayopen = 1 };
}
#[no_mangle]
pub fn endpwent() {
    if !unsafe { pwf.is_null() } {
        unsafe { fclose(pwf) };
        unsafe { pwf = std::ptr::null_mut::<FILE>() };
    }
    unsafe { pw_stayopen = 0 };
}
#[no_mangle]
pub fn getpwent() -> *mut passwd {
    static mut pw: passwd = passwd {
        pw_name: 0 as *const libc::c_char as *mut libc::c_char,
        pw_passwd: 0 as *const libc::c_char as *mut libc::c_char,
        pw_uid: 0,
        pw_gid: 0,
        pw_gecos: 0 as *const libc::c_char as *mut libc::c_char,
        pw_dir: 0 as *const libc::c_char as *mut libc::c_char,
        pw_shell: 0 as *const libc::c_char as *mut libc::c_char,
    };
    static mut pwbuf: [libc::c_char; LINE_MAX as usize] = [0; LINE_MAX as usize];
    let mut len: size_t = 0;
    let mut id: id_t = 0;
    let mut cp: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut colon: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut errstr: *const libc::c_char = std::ptr::null_mut::<libc::c_char>();
    unsafe {
        loop {
            colon = fgets(
                pwbuf.as_mut_ptr(),
                ::core::mem::size_of::<[libc::c_char; 2048]>() as libc::c_ulong as libc::c_int,
                pwf,
            );
            if colon.is_null() {
                return std::ptr::null_mut::<passwd>();
            }
            memset(
                &mut pw as *mut passwd as *mut libc::c_void,
                0 as libc::c_int,
                ::core::mem::size_of::<passwd>() as libc::c_ulong,
            );
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if colon.is_null() {
                continue;
            }
            let fresh0 = colon;
            colon = colon.offset(1);
            *fresh0 = '\0' as i32 as libc::c_char;
            pw.pw_name = cp;
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if colon.is_null() {
                continue;
            }
            let fresh1 = colon;
            colon = colon.offset(1);
            *fresh1 = '\0' as i32 as libc::c_char;
            pw.pw_passwd = cp;
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if colon.is_null() {
                continue;
            }
            let fresh2 = colon;
            colon = colon.offset(1);
            *fresh2 = '\0' as i32 as libc::c_char;
            id = sudo_strtoid_v2(cp, &mut errstr);
            if !errstr.is_null() {
                continue;
            }
            pw.pw_uid = id;
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if colon.is_null() {
                continue;
            }
            let fresh3 = colon;
            colon = colon.offset(1);
            *fresh3 = '\0' as i32 as libc::c_char;
            id = sudo_strtoid_v2(cp, &mut errstr);
            if !errstr.is_null() {
                continue;
            }
            pw.pw_gid = id;
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if colon.is_null() {
                continue;
            }
            let fresh4 = colon;
            colon = colon.offset(1);
            *fresh4 = '\0' as i32 as libc::c_char;
            pw.pw_gecos = cp;
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if !colon.is_null() {
                break;
            }
        }
        let fresh5 = colon;
        colon = colon.offset(1);
        *fresh5 = '\0' as i32 as libc::c_char;
        pw.pw_dir = cp;
        pw.pw_shell = colon;
        len = strlen(colon);
        if len > 0 as libc::c_int as libc::c_ulong
            && *colon.offset(len.wrapping_sub(1 as libc::c_int as libc::c_ulong) as isize)
                as libc::c_int
                == '\n' as i32
        {
            *colon.offset(len.wrapping_sub(1 as libc::c_int as libc::c_ulong) as isize) =
                '\0' as i32 as libc::c_char;
        }
        &mut pw
    }
}
#[no_mangle]
pub fn getpwnam(mut name: *const libc::c_char) -> *mut passwd {
    let mut pw: *mut passwd = std::ptr::null_mut::<passwd>();
    if unsafe { pwf.is_null() } {
        unsafe { pwf = fopen(pwfile, b"r\0" as *const u8 as *const libc::c_char) };
        if unsafe { pwf.is_null() } {
            return std::ptr::null_mut::<passwd>();
        }
        unsafe { fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC) };
    } else {
        unsafe { rewind(pwf) };
    }
    loop {
        pw = getpwent();
        if pw.is_null() {
            break;
        }
        if unsafe { strcmp((*pw).pw_name, name) } == 0 as libc::c_int {
            break;
        }
    }
    if unsafe { pw_stayopen } == 0 {
        unsafe { fclose(pwf) };
        unsafe { pwf = std::ptr::null_mut::<FILE>() };
    }
    pw
}
#[no_mangle]
pub fn getpwuid(mut uid: uid_t) -> *mut passwd {
    let mut pw: *mut passwd = std::ptr::null_mut::<passwd>();
    if unsafe { pwf.is_null() } {
        unsafe { pwf = fopen(pwfile, b"r\0" as *const u8 as *const libc::c_char) };
        if unsafe { pwf.is_null() } {
            return std::ptr::null_mut::<passwd>();
        }
        unsafe { fcntl(fileno(pwf), 2 as libc::c_int, 1 as libc::c_int) };
    } else {
        unsafe { rewind(pwf) };
    }
    loop {
        pw = getpwent();
        if pw.is_null() {
            break;
        }
        if (unsafe { *pw }).pw_uid == uid {
            break;
        }
    }
    if unsafe { pw_stayopen } == 0 {
        unsafe { fclose(pwf) };
        unsafe { pwf = std::ptr::null_mut::<FILE>() };
    }
    pw
}
#[no_mangle]
pub fn setgrfile(mut file: *const libc::c_char) {
    unsafe { grfile = file };
    if !unsafe { grf.is_null() } {
        endgrent();
    }
}
#[no_mangle]
pub fn setgrent() {
    if unsafe { grf.is_null() } {
        unsafe { grf = fopen(grfile, b"r\0" as *const u8 as *const libc::c_char) };
        if !unsafe { grf.is_null() } {
            unsafe { fcntl(fileno(grf), F_SETFD, FD_CLOEXEC) };
        }
    } else {
        unsafe { rewind(grf) };
    }
    unsafe { gr_stayopen = 1 };
}
#[no_mangle]
pub fn endgrent() {
    if !unsafe { grf.is_null() } {
        unsafe { fclose(grf) };
        unsafe { grf = std::ptr::null_mut::<FILE>() };
    }
    unsafe { gr_stayopen = 0 };
}
#[no_mangle]
pub fn getgrent() -> *mut group {
    static mut gr: group = group {
        gr_name: 0 as *const libc::c_char as *mut libc::c_char,
        gr_passwd: 0 as *const libc::c_char as *mut libc::c_char,
        gr_gid: 0,
        gr_mem: 0 as *const *mut libc::c_char as *mut *mut libc::c_char,
    };
    static mut grbuf: [libc::c_char; 2048] = [0; 2048];
    static mut gr_mem: [*mut libc::c_char; 201] =
        [0 as *const libc::c_char as *mut libc::c_char; 201];
    let mut len: size_t = 0;
    let mut id: id_t = 0;
    let mut cp: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut colon: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut errstr: *const libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut n: libc::c_int = 0;
    unsafe {
        loop {
            colon = fgets(
                grbuf.as_mut_ptr(),
                ::core::mem::size_of::<[libc::c_char; 2048]>() as libc::c_ulong as libc::c_int,
                grf,
            );
            if colon.is_null() {
                return std::ptr::null_mut::<group>();
            }
            memset(
                &mut gr as *mut group as *mut libc::c_void,
                0 as libc::c_int,
                ::core::mem::size_of::<group>() as libc::c_ulong,
            );
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if colon.is_null() {
                continue;
            }
            let fresh6 = colon;
            colon = colon.offset(1);
            *fresh6 = '\0' as i32 as libc::c_char;
            gr.gr_name = cp;
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if colon.is_null() {
                continue;
            }
            let fresh7 = colon;
            colon = colon.offset(1);
            *fresh7 = '\0' as i32 as libc::c_char;
            gr.gr_passwd = cp;
            cp = colon;
            colon = strchr(cp, ':' as i32);
            if colon.is_null() {
                continue;
            }
            let fresh8 = colon;
            colon = colon.offset(1);
            *fresh8 = '\0' as i32 as libc::c_char;
            id = sudo_strtoid_v2(cp, &mut errstr);
            if errstr.is_null() {
                break;
            }
        }
        gr.gr_gid = id;
        len = strlen(colon);
        if len > 0 as libc::c_int as libc::c_ulong
            && *colon.offset(len.wrapping_sub(1 as libc::c_int as libc::c_ulong) as isize)
                as libc::c_int
                == '\n' as i32
        {
            *colon.offset(len.wrapping_sub(1 as libc::c_int as libc::c_ulong) as isize) =
                '\0' as i32 as libc::c_char;
        }
        if *colon as libc::c_int != '\0' as i32 {
            let mut last: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
            gr.gr_mem = gr_mem.as_mut_ptr();
            cp = strtok_r(colon, b",\0" as *const u8 as *const libc::c_char, &mut last);
            n = 0 as libc::c_int;
            while !cp.is_null() && n < GRMEM_MAX {
                let fresh9 = &mut *(gr.gr_mem).offset(n as isize);
                *fresh9 = cp;
                cp = strtok_r(
                    std::ptr::null_mut::<libc::c_char>(),
                    b",\0" as *const u8 as *const libc::c_char,
                    &mut last,
                );
                n += 1;
            }
            let fresh10 = n;
            n += 1;
            let fresh11 = &mut *(gr.gr_mem).offset(fresh10 as isize);
            *fresh11 = std::ptr::null_mut::<libc::c_char>();
        } else {
            gr.gr_mem = std::ptr::null_mut::<*mut libc::c_char>();
        }
        &mut gr
    }
}
#[no_mangle]
pub fn getgrnam(mut name: *const libc::c_char) -> *mut group {
    let mut gr: *mut group = std::ptr::null_mut::<group>();
    if unsafe { grf.is_null() } {
        unsafe { grf = fopen(grfile, b"r\0" as *const u8 as *const libc::c_char) };
        if unsafe { grf.is_null() } {
            return std::ptr::null_mut::<group>();
        }
        unsafe { fcntl(fileno(grf), 2 as libc::c_int, 1 as libc::c_int) };
    } else {
        unsafe { rewind(grf) };
    }
    loop {
        gr = getgrent();
        if gr.is_null() {
            break;
        }
        if unsafe { strcmp((*gr).gr_name, name) } == 0 as libc::c_int {
            break;
        }
    }
    if unsafe { gr_stayopen } == 0 {
        unsafe { fclose(grf) };
        unsafe { grf = std::ptr::null_mut::<FILE>() };
    }
    gr
}
#[no_mangle]
pub fn getgrgid(mut gid: gid_t) -> *mut group {
    let mut gr: *mut group = std::ptr::null_mut::<group>();
    if unsafe { grf.is_null() } {
        unsafe { grf = fopen(grfile, b"r\0" as *const u8 as *const libc::c_char) };
        if unsafe { grf.is_null() } {
            return std::ptr::null_mut::<group>();
        }
        unsafe { fcntl(fileno(grf), F_SETFD, FD_CLOEXEC) };
    } else {
        unsafe { rewind(grf) };
    }
    loop {
        gr = getgrent();
        if gr.is_null() {
            break;
        }
        if (unsafe { *gr }).gr_gid == gid {
            break;
        }
    }
    if unsafe { gr_stayopen } == 0 {
        unsafe { fclose(grf) };
        unsafe { grf = std::ptr::null_mut::<FILE>() };
    }
    gr
}

/*
 * Copied from getgrouplist.c
 */
#[no_mangle]
pub fn sudo_getgrouplist2_v1(
    mut name: *const libc::c_char,
    mut basegid: gid_t,
    mut groupsp: *mut *mut gid_t,
    mut ngroupsp: *mut libc::c_int,
) -> libc::c_int {
    let mut groups: *mut gid_t = unsafe { *groupsp };
    let mut grpsize: libc::c_int = unsafe { *ngroupsp };
    let mut i: libc::c_int = 0;
    let mut ngroups: libc::c_int = 1 as libc::c_int;
    let mut ret: libc::c_int = -(1 as libc::c_int);
    let mut grp: *mut group = std::ptr::null_mut::<group>();
    if groups.is_null() {
        /* Dynamically-sized group vector. */
        grpsize = unsafe { sysconf(_SC_NGROUPS_MAX as libc::c_int) } as libc::c_int;
        if grpsize < 0 as libc::c_int {
            grpsize = NGROUPS_MAX as libc::c_int;
        }
        groups = unsafe {
            reallocarray(
                std::ptr::null_mut::<libc::c_void>(),
                grpsize as size_t,
                (4 as libc::c_int as libc::c_ulong)
                    .wrapping_mul(::core::mem::size_of::<gid_t>() as libc::c_ulong),
            )
        } as *mut gid_t;
        if groups.is_null() {
            return -(1 as libc::c_int);
        }
        grpsize <<= 2 as libc::c_int;
        /* Static group vector. */
    } else if grpsize < 1 as libc::c_int {
        return -(1 as libc::c_int);
    }
    /* We support BSD semantics where the first element is the base gid */
    unsafe { *groups.offset(0 as libc::c_int as isize) = basegid };
    setgrent();
    unsafe {
        loop {
            grp = getgrent();
            if grp.is_null() {
                ret = 0;
                break;
            }
            if (*grp).gr_gid == basegid || ((*grp).gr_mem).is_null() {
                continue;
            }
            i = 0 as libc::c_int;
            while !(*((*grp).gr_mem).offset(i as isize)).is_null() {
                if strcmp(name, *((*grp).gr_mem).offset(i as isize)) == 0 as libc::c_int {
                    break;
                }
                i += 1;
            }
            if (*((*grp).gr_mem).offset(i as isize)).is_null() {
                continue; /* user not found */
            }

            /* Only add if it is not the same as an existing gid */
            i = 0 as libc::c_int;
            while i < ngroups {
                if (*grp).gr_gid == *groups.offset(i as isize) {
                    break;
                }
                i += 1;
            }
            if i != ngroups {
                continue;
            }
            if ngroups == grpsize {
                let mut tmp: *mut gid_t = std::ptr::null_mut::<gid_t>();
                if !(*groupsp).is_null() {
                    /* Static group vector. */
                    break;
                }
                tmp = reallocarray(
                    groups as *mut libc::c_void,
                    grpsize as size_t,
                    (2 as libc::c_int as libc::c_ulong)
                        .wrapping_mul(::core::mem::size_of::<gid_t>() as libc::c_ulong),
                ) as *mut gid_t;
                if tmp.is_null() {
                    free(groups as *mut libc::c_void);
                    groups = std::ptr::null_mut::<gid_t>();
                    ngroups = 0 as libc::c_int;
                    break;
                } else {
                    groups = tmp;
                    grpsize <<= 1 as libc::c_int;
                }
            }
            let fresh12 = ngroups;
            ngroups += 1;
            *groups.offset(fresh12 as isize) = (*grp).gr_gid;
        }

        endgrent();
        *groupsp = groups;
        *ngroupsp = ngroups;
    }
    ret
}
